﻿using System.Reflection;
using ApiConceptsFramework;
using ApiConceptsFramework.Contract;
using ApiConceptsFramework.HCs;
using FluentAssertions;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;

namespace test.ApiConceptsFramework.HCs
{
	[TestFixture]
	public class FluentInterfaceTests
	{
		class TestClass
		{
// ReSharper disable UnusedMember.Local
// ReSharper disable UnusedParameter.Local
			public TestClass FluentMethod1(int p1) { return null; }
			public TestClass FluentMethod2(int p1, int p2) { return null; }
			public TestClass FluentMethod3(int p1, int p2, int p3) { return null; }
// ReSharper restore UnusedParameter.Local
// ReSharper restore UnusedMember.Local
		}

		private FluentInterface _pattern;
		private MethodInfo[] _testMethods;

		[SetUp]
		public void SetUp()
		{
			_pattern = new FluentInterface();
			_testMethods = new[]
				{
					typeof(TestClass).GetMethod("FluentMethod1"),
					typeof(TestClass).GetMethod("FluentMethod2"),
					typeof(TestClass).GetMethod("FluentMethod3")
				};
		}

		[Test]
		public void Returns_null_when_input_data_is_null()
		{
			_pattern.Evaluate(null, null, null, null).Should().BeNull();
		}

		[Test]
		public void Returns_null_when_list_of_method_chains_is_empty()
		{
			_pattern.Evaluate(null, new ConceptInstance[]{}, new FluentInterfaceInputData{FluentMethodChains = new List<FluentMethodChain>()}, null)
				.Should().BeNull();
		}

		//[Test]
		//public void Chain_with_three_methods_has_correct_complexity()
		//{
		//	//Arrange
		//	var patternData = new FluentInterfaceInputData();
		//	patternData.FluentMethodChains.Add(new FluentMethodChain {Methods = _testMethods.ToList(), NumberOfUsages = 1});
		//	var conceptData = new[]
		//		{
		//			new ConceptInstance{Target = new MeasurableTarget{Member = _testMethods[0]}}
		//		};

		//	//Act
		//	var result = _pattern.Evaluate(null, conceptData, patternData);

		//	//Assert
		//	result.Should().NotBeNull();
		//	result.GeneralComplexity.Should().Be(0);
		//	result.ComplexityData.Should().HaveCount(1);
		//	result.ComplexityData[0].UsageComplexity.Should().Be(FluentInterface.BaseComplexityOfChainedMethod);
		//}

		//[Test]
		//public void Chain_with_three_methods_adds_correct_complexity_to_concept_instances()
		//{
		//	//Arrange
		//	var patternData = new FluentInterfaceInputData();
		//	patternData.FluentMethodChains.Add(new FluentMethodChain { Methods = _testMethods.ToList(), NumberOfUsages = 1 });
		//	var conceptData = new[]
		//		{
		//			new ConceptInstance{Target = new MeasurableTarget{Member = _testMethods[0]}, NumberOfUsages = 1},
		//			new ConceptInstance{Target = new MeasurableTarget{Member = _testMethods[1]}, NumberOfUsages = 1},
		//			new ConceptInstance{Target = new MeasurableTarget{Member = _testMethods[2]}, NumberOfUsages = 1}
		//		};

		//	//Act
		//	var result = _pattern.Evaluate(null, conceptData, patternData);

		//	//Assert
		//	result.Should().NotBeNull();
		//	conceptData[0].PatternData.Should().HaveCount(1);
		//	conceptData[0].PatternData[0].UsageComplexity.Should().Be(-5); //method with 2 params
		//	conceptData[1].PatternData.Should().HaveCount(1);
		//	conceptData[1].PatternData[0].UsageComplexity.Should().Be(-7); //method with 3 params
		//	conceptData[2].PatternData.Should().HaveCount(1);
		//	conceptData[2].PatternData[0].UsageComplexity.Should().Be(-9); //method with 4 params
		//}

		[Test]
		public void Type_of_hcInputData_is_correct()
		{
			_pattern.InputDataType.Should().Be(typeof(FluentInterfaceInputData));
		}
	}
}
